package com.assa.jco.handler;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;

import com.assa.subscriber.EventSubscriber;
import com.sap.conn.jco.AbapException;
import com.sap.conn.jco.JCoField;
import com.sap.conn.jco.JCoFieldIterator;
import com.sap.conn.jco.JCoFunction;
import com.sap.conn.jco.JCoRecordFieldIterator;
import com.sap.conn.jco.JCoStructure;
import com.sap.conn.jco.JCoTable;
import com.sap.conn.jco.server.JCoServerContext;

public abstract class AbstractFunctionHandler implements FunctionHandler {

	protected EventSubscriber subscriber;
	private String functionName;

	public void setEventSubscriber(EventSubscriber subscriber) {
		this.subscriber = subscriber;
	}

	public String getFunctionName() {
		return this.functionName;
	}

	public void setFunctionName(String name) {
		this.functionName = name;
	}

	protected abstract Log getLog();

	protected abstract void logExtraInfo(JCoServerContext serverCtx, JCoFunction function);

	protected void logCallInfo(JCoServerContext serverCtx, JCoFunction function) {
		if(getLog().isDebugEnabled()) {
			getLog().debug("----------------------------------------------------------------");
			getLog().debug("call              : " + function.getName());
			getLog().debug("ConnectionId      : " + serverCtx.getConnectionID());
			getLog().debug("SessionId         : " + serverCtx.getSessionID());
			getLog().debug("TID               : " + serverCtx.getTID());
			getLog().debug("repository name   : " + serverCtx.getRepository().getName());
			getLog().debug("is in transaction : " + serverCtx.isInTransaction());
			getLog().debug("is stateful       : " + serverCtx.isStatefulSession());
			getLog().debug("----------------------------------------------------------------");
			getLog().debug("gwhost: " + serverCtx.getServer().getGatewayHost());
			getLog().debug("gwserv: " + serverCtx.getServer().getGatewayService());
			getLog().debug("progid: " + serverCtx.getServer().getProgramID());
			getLog().debug("----------------------------------------------------------------");
			getLog().debug("attributes  : ");
			getLog().debug(serverCtx.getConnectionAttributes().toString());
			getLog().debug("----------------------------------------------------------------");
			getLog().debug("CPIC conversation ID: " + serverCtx.getConnectionAttributes().getCPICConversationID());
			getLog().debug("----------------------------------------------------------------");
			getLog().debug("Exports: ");
		
			JCoFieldIterator iterator = function.getImportParameterList().getFieldIterator();
		
			while (iterator.hasNextField()) {
				JCoField field = iterator.nextField();
				getLog().debug("Field :" + field.getName() + " tipo: " + field.getTypeAsString());
			}
		}

		this.logExtraInfo(serverCtx, function);
	}

	public void handleRequest(JCoServerContext serverCtx, JCoFunction function) throws AbapException {
		logCallInfo(serverCtx, function);
		Map<String, String> params = this.processRequest(serverCtx, function);
		if(this.subscriber != null) {
			subscriber.notifyEvent(params);
		}
	}
	
	protected abstract Map<String, String> processRequest(JCoServerContext serverCtx, JCoFunction function);

	protected Map<String, String> loadStructure(JCoStructure jcoStruct, String prefix) {
		JCoRecordFieldIterator iterator = jcoStruct.getRecordFieldIterator();
		return extractFieldValues(iterator, prefix);
	}



	protected List<Map<String, String>> loadTable(JCoTable table, String prefix) {
		List<Map<String, String>> res = new ArrayList<Map<String, String>>();
		if (table.getNumRows() > 0) {
		      table.firstRow();
		      do {
		    	  JCoRecordFieldIterator iterator = table.getRecordFieldIterator();
		    	  Map<String,String> record = extractFieldValues(iterator,prefix);
		    	  res.add(record);
		      }
		      while(table.nextRow());
		  }
		return res;
	}
	
	private Map<String, String> extractFieldValues(JCoRecordFieldIterator iterator, String prefix) {
		Map<String, String> container = new HashMap<String, String>();
		while (iterator.hasNextField()) {
			JCoField field = iterator.nextField();
			container.put(prefix + "_" + field.getName(), field.getString());
		}
		return container;
	}
}
